package com.wang.springbootinit.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wang.springbootinit.common.BaseResponsePage;
import com.wang.springbootinit.common.ErrorCode;
import com.wang.springbootinit.constant.BISystemEnum;
import com.wang.springbootinit.constant.CommonConstant;
import com.wang.springbootinit.constant.UserConstant;
import com.wang.springbootinit.exception.BusinessException;
import com.wang.springbootinit.mapper.SourceFileMapper;
import com.wang.springbootinit.minio.MinioUtil;
import com.wang.springbootinit.model.entity.Chart;
import com.wang.springbootinit.model.entity.SourceFile;
import com.wang.springbootinit.model.entity.User;
import com.wang.springbootinit.model.param.SourceFileOperateParam;
import com.wang.springbootinit.model.param.SourceFileQueryParam;
import com.wang.springbootinit.model.vo.SourceFileVO;
import com.wang.springbootinit.service.ChartService;
import com.wang.springbootinit.service.SourceFileService;
import com.wang.springbootinit.service.UserService;
import com.wang.springbootinit.utils.ConvertUtil;
import com.wang.springbootinit.utils.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
* @author wang3
* @description 针对表【source_file】的数据库操作Service实现
* @createDate 2024-03-11 15:57:41
*/
@Service
@Slf4j
public class SourceFileServiceImpl extends ServiceImpl<SourceFileMapper, SourceFile>
    implements SourceFileService{
    private static final Logger LOGGER = LoggerFactory.getLogger(SourceFileServiceImpl.class);
    @Resource
    private UserService userService;
    @Resource
    private MinioUtil minioUtil;
    @Resource
    private ChartService chartService;

    /**
     * 分页查询
     * @param param
     * @return
     */
    @Override
    public BaseResponsePage<List<SourceFileVO>> listPage(SourceFileQueryParam param,HttpServletRequest request) {
        LOGGER.info("SourceFileServiceImpl listPage param:{}", JSONUtil.toJsonStr(param));
        try {
            long current = param.getCurrent();
            long size = param.getPageSize();
            User loginUser = userService.getUser(request);
            Page<SourceFile> sourceFilePage = this.page(new Page<>(current, size), this.getQueryWrapper(param,loginUser));
            if(ObjectUtil.isNull(sourceFilePage)){
                return new BaseResponsePage<>(BISystemEnum.ERROR.getCode(),new ArrayList<>(),BISystemEnum.ERROR.getMsg());
            }
            if(CollectionUtil.isEmpty(sourceFilePage.getRecords())){
                return new BaseResponsePage<>(BISystemEnum.SUCCESS.getCode(),new ArrayList<>(),BISystemEnum.SUCCESS.getMsg(),(int)sourceFilePage.getCurrent(),(int)sourceFilePage.getSize(),(int)sourceFilePage.getTotal());

            }
            List<SourceFile> sourceFilePageRecords = sourceFilePage.getRecords();
            List<Long> userIdList = sourceFilePageRecords.stream().map(SourceFile::getUserId).collect(Collectors.toList());
            List<User> users = userService.listByIds(userIdList);
            Map<Long, User> userMap = new HashMap<>();
            if(CollectionUtil.isNotEmpty(users)){
                userMap = users.stream().collect(Collectors.toMap(User::getId, user -> user, (u1, u2) -> u1));
            }
            Map<Long, User> finalUserMap = userMap;
            //查询图表信息
            List<Long> chartIdList = sourceFilePageRecords.stream().map(SourceFile::getChartId).collect(Collectors.toList());
            List<Chart> chartList = chartService.listByIds(chartIdList);
            Map<Long, Chart> chartMap = chartList.stream().collect(Collectors.toMap(Chart::getId, x -> x, (c1, c2) -> c1));
            List<SourceFileVO> sourceFileVOList = sourceFilePage.getRecords().stream().map(x -> {
                SourceFileVO sourceFileVO = new SourceFileVO();
                BeanUtils.copyProperties(x,sourceFileVO);
                User user = finalUserMap.get(x.getUserId());
                sourceFileVO.setUser(ConvertUtil.UserVOConvert(user));
                sourceFileVO.setChartVO(ConvertUtil.ChartVOConvert(chartMap.get(x.getChartId())));
                return sourceFileVO;
            }).collect(Collectors.toList());

//            sourceFileVOList = sourceFileVOList.stream().sorted(Comparator.comparing(SourceFileVO::getCreateTime).reversed()).collect(Collectors.toList());

            long number = 1L;
            for (SourceFileVO sourceFileVO : sourceFileVOList) {
                sourceFileVO.setNumber(number++);
            }
            return new BaseResponsePage<>(BISystemEnum.SUCCESS.getCode(),sourceFileVOList,BISystemEnum.SUCCESS.getMsg(),(int)sourceFilePage.getCurrent(),(int)sourceFilePage.getSize(),(int)sourceFilePage.getTotal());
        } catch (Exception e) {
            LOGGER.error("SourceFileServiceImpl listPage exception:",e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }



    }

    /**
     * 删除文件
     * @param param
     * @param request
     * @return
     */
    @Override
    public Boolean deleteById(SourceFileOperateParam param, HttpServletRequest request) {
        LOGGER.info("SourceFileServiceImpl deleteById param:{}", JSONUtil.toJsonStr(param));
        try {
            SourceFile sourceFile = this.getById(param.getId());
            if(ObjectUtil.isNotNull(sourceFile)){
                boolean result = this.removeById(sourceFile.getId());
                if(StrUtil.isNotEmpty(sourceFile.getObjectFileName()) && result){
                    boolean remove = minioUtil.remove(sourceFile.getObjectFileName());
                    log.info("SourceFileServiceImpl deleteById removeResult:{},fileRemoveResult:{}",request,remove);
                }
                return result;
            }
            return Boolean.FALSE;
        } catch (Exception e) {
            LOGGER.error("SourceFileServiceImpl deleteById exception:", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
    }

    /**
     * 下载文件
     * @param param
     * @param request
     * @return
     */
    @Override
    public Boolean download(SourceFileOperateParam param, HttpServletRequest request, HttpServletResponse response) {
        try {
            SourceFile sourceFile = this.getById(param.getId());
            String objectFileName = sourceFile.getObjectFileName();
            String originalFilename = sourceFile.getOriginalFilename();
            minioUtil.download(objectFileName,originalFilename,response);
            return Boolean.TRUE;
        } catch (Exception e) {
            LOGGER.error("download Exception:",e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
    }


    public QueryWrapper<SourceFile> getQueryWrapper(SourceFileQueryParam param,User loginUser) {
        if (param == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        QueryWrapper<SourceFile> queryWrapper = new QueryWrapper<>();
        if(!loginUser.getUserRole().equals(UserConstant.ADMIN_ROLE)){
            queryWrapper.eq(ObjectUtil.isNotNull(loginUser.getId()), "userId", loginUser.getId());
        }
        queryWrapper.eq(param.getId() != null, "id", param.getId());
        queryWrapper.eq(param.getChartId() != null, "chartId", param.getChartId());
        queryWrapper.like(StringUtils.isNotBlank(param.getFileName()), "originalFilename", param.getFileName());
//        queryWrapper.orderBy(SqlUtils.validSortField(param.getSortField()), param.equals(CommonConstant.SORT_ORDER_ASC),
//                param.getSortField());
        queryWrapper.orderByDesc("createTime");
        return queryWrapper;
    }
}




